package View;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.management.ManagementFactory;

import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import MonteCarloMonoThread.MonteCarloMonoThreadSimulation;
import MonteCarloMultiThread.MonteCarloSimulation;

/**
 * The GUI of the application
 * @author adrien
 *
 */


public class MonteCarloGUI extends JFrame implements ActionListener, Updatable,WindowListener,ListSelectionListener,PropertyChangeListener {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JButton bRunMulti,bRunMono;
	private JList<String> list;
	private DefaultListModel<String> listModel;
	private JLabel infoRAM;
	private JLabel infoThread;
	private JPanel main;
	private JPanel p0;
	private JPanel p1;
	private JPanel topPan;
	private JPanel p2;
	private JPanel p3;
	private JPanel p4;
	private JPanel p5;
	private static Color cyan = new Color(223, 242, 255);
	
	
	Updatable that=this;
	MonteCarloMultiThread.MonteCarloSimulation mcs;
	MonteCarloMonoThreadSimulation mcsMono;
	
	//MonteCarloParameters
	private double S,X,T,r,b,v;
	private int nSteps,nSimulations;
	private String CallPutFlag;
	private JProgressBar progressBar;
	
	
	public MonteCarloGUI (){
		
		
        final ImageIcon icon = new ImageIcon("MonteCarlo.jpg");
        
        //The main panel contains the background and all the other panels
		main = new JPanel(new BorderLayout()){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			protected void paintComponent(Graphics g)
			{
				//  Display image
				g.drawImage(icon.getImage(), 0, 0, null); 	
				super.paintComponent(g);
			}
		};
		main.setOpaque(false);
		
		
		//Panel which holds the list
		GridLayout grid = new GridLayout(4,1,0,0);
		grid.setColumns(1);
		grid.setRows(4);
		grid.setHgap(0);
		grid.setVgap(0);
		p0 = new JPanel(grid);
		p0.setLayout(grid);
		p0.setOpaque( false );
        p0.add(new JLabel(System.getenv("PROCESSOR_ARCHITECTURE")));
        p0.add(new JLabel("Core ="+System.getenv("NUMBER_OF_PROCESSORS")));
        p0.add(new JLabel("Max memory ="+Runtime.getRuntime().maxMemory()/1000000+" M"));
        p0.add(infoRAM = new JLabel());
        p0.add(infoThread = new JLabel());
        
		//Panel which holds the list
        p1 = new JPanel(new FlowLayout());
        p1.setOpaque( false );
        
		listModel = new DefaultListModel<String>();
		
		list = new JList<String>(listModel);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.setSelectedIndex(0);
        list.setVisibleRowCount(5);
        list.setBackground(cyan);
        JScrollPane listScrollPane = new JScrollPane(list);
        p1.add(listScrollPane);
        
        //topPan holds p0 and p1 which are at the top of the windows
        topPan = new JPanel (new BorderLayout());
        topPan.add(p0, BorderLayout.NORTH);
        topPan.add(p1, BorderLayout.SOUTH);
        topPan.setOpaque(false);
        
       
        //Panel which holds the Results       
        p2 = new JPanel ();
        p2.setOpaque(false);
        GridLayout layout = new GridLayout(20,0);
		p2.setLayout(layout);
        p2.add(new JLabel("Calculation",10));
        p2.setSize(100, p2.getHeight());

        
        //Panel which holds the Times
        
        p4 = new JPanel(new GridLayout(20,0));
        p4.setOpaque( false );
        p4.add(new JLabel("Time (s)",10));
        
        //Panel which holds the thread count
        p5 = new JPanel(new GridLayout(20,0));
        p5.setOpaque( false );
        JLabel nbThreads = new JLabel("Nb Threads");
        nbThreads.setHorizontalAlignment(JLabel.CENTER);
        p5.add(nbThreads);
        
        
        //Panel which holds the buttons
        p3 = new JPanel(new FlowLayout());
        p3.setOpaque( false );
        bRunMulti = new JButton ("Run MultiThread");
        bRunMulti.setBackground(cyan);
        p3.add(bRunMulti);
        bRunMono = new JButton ("Run MonoThread");
        bRunMono.setBackground(cyan);
        p3.add(bRunMono);
        
        progressBar = new JProgressBar();
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        progressBar.setBackground(cyan);
        p3.add(progressBar);
        

        //Add to the main Panel
        main.add(topPan, BorderLayout.NORTH);
        main.add(p2, BorderLayout.WEST);
        main.add(p4, BorderLayout.EAST);
        main.add(p5, BorderLayout.CENTER);
        main.add(p3, BorderLayout.SOUTH);
        
        //Add panels on the Frame
        getContentPane().add(main);
		
		
		//Add actionListener
		bRunMulti.addActionListener(this);
		bRunMono.addActionListener(this);
		addWindowListener(this);
		list.addListSelectionListener(this);
		

		
		
        
		
		
	}
	
	public static void main (String []args){
		
		
		MonteCarloGUI frame = new MonteCarloGUI();
		frame.setTitle("Monte Carlo");
		frame.setSize(500, 500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		frame.setResizable(false);
	}
	
	
	@Override
	public void actionPerformed(ActionEvent e) {
		
		if(e.getActionCommand().equals("Run MultiThread")){
			
			if(list.getSelectedIndex()==-1){ //if nothing is selected
				list.setSelectedIndex(0);
			}
			
			if (list.getSelectedIndex()!=-1){ //the list model is not empty
				try {
					
					
							JLabel lRetult = new JLabel();
							JLabel lTime = new JLabel();
							JLabel lThread = new JLabel();
							
							
							
							mcs = new MonteCarloSimulation(that,lRetult,lTime,lThread,CallPutFlag,S,X,T,r,b,v,nSteps,nSimulations);
							Thread thread = new Thread(mcs);
							thread.start();
							
					
					
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			else {
				JOptionPane.showMessageDialog(null,"Nothing in the list");
			}
			
			
			
		}
		
		if(e.getActionCommand().equals("Run MonoThread")){
			
			if(list.getSelectedIndex()==-1){ //if nothing is selected
				list.setSelectedIndex(0);
			}
			
			if (list.getSelectedIndex()!=-1){ //the list model is not empty
				try {
					JLabel lRetult = new JLabel();
					JLabel lTime = new JLabel();
					JLabel lThread = new JLabel();
					mcsMono = new MonteCarloMonoThreadSimulation(that,lRetult,lTime,lThread,CallPutFlag,S,X,T,r,b,v,nSteps,nSimulations);
					Thread thread = new Thread(mcsMono);
					thread.start();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			else {
				JOptionPane.showMessageDialog(null,"Nothing in the list");
			}
			
			
			
		}
		
	}

	public void displayIntermediateValue(double value,JLabel label) {
		label.setText(String.valueOf(value));
	}
	public void addLabelWest(JLabel label){
		if (p2.getComponentCount()>19){ //if there is too many Jlabel, we delete it all
			p2.removeAll();
			p2.add(new JLabel("Calculation",10));
		}
		p2.add(label);

	}
	public void addLabelEast(JLabel label){
		if (p4.getComponentCount()>19){ //if there is too many Jlabel, we delete it all
			p4.removeAll();
			p4.add(new JLabel("Time (s)",10));
		}
		p4.add(label);
	}
	public void addLabelCenter (JLabel label){
		if (p5.getComponentCount()>19){ //if there is too many Jlabel, we delete it all
			p5.removeAll();
			JLabel lNbThread = new JLabel("Nb Threads");
			lNbThread.setHorizontalAlignment(JLabel.CENTER);
	        p5.add(lNbThread);
		}
		JLabel nbLabel = label;
		nbLabel.setHorizontalAlignment(JLabel.CENTER);
		p5.add(nbLabel);
	}
	public void setProgressBar(int value){
		progressBar.setValue(value);
	}
	
	
	public void loadfile(){
		try{

		    BufferedReader br = new BufferedReader(new FileReader("resources.txt"));
		    String strLine;
		    //Read File Line By Line
		    while ((strLine = br.readLine()) != null)   {
		      // Print the content on the console
		      listModel.addElement (strLine);
		    }
		    //Close the input stream
		    br.close();
		    }catch (Exception e){//Catch exception if any
		      System.err.println("Error: " + e.getMessage());
		    }
	}
	
	public void propertyChange(PropertyChangeEvent evt) {
	        if ("progress" == evt.getPropertyName()) {
	            int progress = (Integer) evt.getNewValue();
	            progressBar.setValue(progress);
	        }
	}

	@Override
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void windowOpened(WindowEvent arg0) {
		loadfile();
		
		Thread infoRAMThread = new Thread(){
			public void run (){
				while(true){
					try {
						sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					infoRAM.setText("Used memory ="+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/1000000+" M");
				}
				
			}
		};
		
		infoRAMThread.start();
		
		Thread infoThreadThread = new Thread(){
			public void run (){
				while(true){
					try {
						sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}					
					infoThread.setText("Total nb Threads ="+ManagementFactory.getThreadMXBean().getThreadCount());
				}
			}
		};
		
		infoThreadThread.start();
		
	}

	@Override
	public void valueChanged(ListSelectionEvent arg0) {
		String parameters[] = list.getSelectedValue().toString().split(",");
		CallPutFlag=parameters[0] ;
		S=Double.parseDouble(parameters[1]);
		X=Double.parseDouble(parameters[2]);
		T=Double.parseDouble(parameters[3]);
		r=Double.parseDouble(parameters[4]);
		b=Double.parseDouble(parameters[5]);
		v=Double.parseDouble(parameters[6]);
		nSteps=Integer.parseInt(parameters[7]);
		nSimulations=Integer.parseInt(parameters[8]);
		System.out.println("CallPutFlag ="+CallPutFlag+"; S ="+S+"; X ="+X+"; T ="+T+"; r ="+r+"; b ="+b+"; v ="+v+"; nSteps ="+nSteps+"; nSimulations ="+nSimulations);
		
	}
	
	
}
